package com.gofaraway.common.domin;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageInfo;
import com.gofaraway.common.util.bean.BeanCopierUtil;
import com.gofaraway.common.util.lambda.LambdaUtil;

import java.io.Serializable;
import java.util.List;
import java.util.Optional;
import java.util.function.Supplier;

/**
 * @author ChenPeng
 * @Date 2024/5/15 11:13
 */
public class PagingResponse<T> implements Serializable {

    public PagingResponse() {
    }

    public PagingResponse(int current, int size, int totalItems, int totalPages, List<T> items) {
        this.current = current;
        this.size = size;
        this.totalItems = totalItems;
        this.totalPages = totalPages;
        this.items = items;
    }

    /**
     * Current page num, must start from 1
     */
    private int current = 1;

    /**
     * Item count in one page
     */
    private int size = 10;

    /**
     * Total items in persistence
     */
    private int totalItems;

    /**
     * Total page count in persistence
     */
    private int totalPages;

    /**
     * Current retrieved data
     */
    private List<T> items;

    /**
     * mybatis -plus 分页插件 返回
     *
     * @param iPage
     * @param <T>
     * @return
     */
    public static <T> PagingResponse<T> pageResponse(IPage<T> iPage) {
        Integer start = Optional.of(iPage.getCurrent()).map(Long::intValue).orElse(1);
        Integer total = Optional.of(iPage.getTotal()).map(Long::intValue).orElse(0);
        Integer size = Optional.of(iPage.getSize()).map(Long::intValue).orElse(1);
        Integer totalPage = Optional.of(iPage.getPages()).map(Long::intValue).orElse(1);
        return new PagingResponse(start, size, total, totalPage, iPage.getRecords());
    }

    /**
     * pageInfo 工具转换
     *
     * @param pageInfo
     * @param <T>
     * @return
     */
    public static <T> PagingResponse<T> pageResponse(PageInfo<T> pageInfo) {
        Integer start = Optional.of(pageInfo.getStartRow()).map(Long::intValue).orElse(1);
        Integer size = Optional.of(pageInfo.getSize()).orElse(1);
        Integer total = Optional.of(pageInfo.getTotal()).map(Long::intValue).orElse(0);
        return new PagingResponse<T>(start, size, total, pageInfo.getPages(), pageInfo.getList());

    }

    /**
     * @param iPage
     * @param targetClass
     * @return cn.sto.transport.common.domain.PagingResponse<V>
     * @date 2021/11/23 6:04 下午
     * @description mybatis-plus分页实体类转换
     * @author guiyuting
     */
    public static <P, V> PagingResponse<V> pageConvert(IPage<P> iPage, Supplier<V> targetClass) {
        Integer start = Optional.of(iPage.getCurrent()).map(Long::intValue).orElse(1);
        Integer total = Optional.of(iPage.getTotal()).map(Long::intValue).orElse(0);
        Integer size = Optional.of(iPage.getSize()).map(Long::intValue).orElse(1);
        Integer totalPage = Optional.of(iPage.getPages()).map(Long::intValue).orElse(1);
        List<V> targetList = LambdaUtil.convertList(iPage.getRecords(), (source) -> {
            V target = targetClass.get();
            BeanCopierUtil.copy(source, target);
            return target;
        });
        return new PagingResponse<V>(start, size, total, totalPage, targetList);
    }

    /**
     * 支持 pageHelpr  Page 对象
     *
     * @param page
     * @param targetClass
     * @param <P>
     * @param <V>
     * @return
     */
    public static <P, V> PagingResponse<V> pageConvert(Page<P> page, Supplier<V> targetClass) {
        Integer start = Optional.of(page.getPageNum()).orElse(1);
        Integer size = Optional.of(page.getPageSize()).orElse(0);
        Integer total = Optional.of(page.getTotal()).map(Long::intValue).orElse(1);
        Integer totalPage = Optional.of(page.getPages()).orElse(1);
        List<V> targetList = LambdaUtil.convertList(page.getResult(), (source) -> {
            V target = targetClass.get();
            BeanCopierUtil.copy(source, target);
            return target;
        });
        return new PagingResponse<V>(start, size, total, totalPage, targetList);
    }

    /**
     * @param pageInfo
     * @param targetClass
     * @return cn.sto.transport.common.domain.PagingResponse<V>
     * @date 2021/11/26 11:15 上午
     * @description pageInfo分页实体类转换
     * @author guiyuting
     */
    public static <P, V> PagingResponse<V> pageConvert(PageInfo<P> pageInfo, Supplier<V> targetClass) {
        Integer start = Optional.of(pageInfo.getStartRow()).map(Long::intValue).orElse(1);
        Integer size = Optional.of(pageInfo.getSize()).orElse(1);
        Integer total = Optional.of(pageInfo.getTotal()).map(Long::intValue).orElse(0);
        List<V> targetList = LambdaUtil.convertList(pageInfo.getList(), (source) -> {
            V target = targetClass.get();
            BeanCopierUtil.copy(source, target);
            return target;
        });
        return new PagingResponse<V>(start, size, total, pageInfo.getPages(), targetList);
    }

    /**
     * @param pagingResponse
     * @param targetClass
     * @return cn.sto.transport.common.domain.PagingResponse<V>
     * @date 2021/12/2 9:18 上午
     * @description PagingResponse实体类转换
     * @author guiyuting
     */
    public static <P, V> PagingResponse<V> pagingResponseConvert(PagingResponse<P> pagingResponse,
                                                                 Supplier<V> targetClass) {
        List<V> targetList = LambdaUtil.convertList(pagingResponse.getItems(), (source) -> {
            V target = targetClass.get();
            BeanCopierUtil.copy(source, target);
            return target;
        });
        return new PagingResponse<V>(pagingResponse.getCurrent(), pagingResponse.getSize(),
                pagingResponse.getTotalItems(), pagingResponse.totalPages, targetList);
    }

    // Accessors ----------------------------------------------

    public List<T> getItems() {
        return items;
    }

    public void setItems(List<T> items) {
        this.items = items;
    }

    public int getCurrent() {
        return current;
    }

    public void setCurrent(int current) {
        this.current = current;
    }

    public int getSize() {
        return size;
    }

    public void setSize(int size) {
        this.size = size;
    }

    public int getTotalItems() {
        return totalItems;
    }

    public void setTotalItems(int totalItems) {
        this.totalItems = totalItems;
    }

    public int getTotalPages() {
        return totalPages;
    }

    public void setTotalPages(int totalPages) {
        this.totalPages = totalPages;
    }

    @Override
    public String toString() {
        return "PagingResponse{" +
                "current=" + current +
                ", size=" + size +
                ", totalItems=" + totalItems +
                ", totalPages=" + totalPages +
                ", items=" + items +
                '}';
    }
}
